import tkinter as tk
from tkinter import ttk, scrolledtext, messagebox
import json
import threading
import time
from simulator_data import (
    simulator_settings, 
    generate_robot_status, 
    generate_gait_data, 
    generate_alert_data,
    generate_and_save_data,
    DataGenerationThread
)

class SimulatorApp:
    def __init__(self, root):
        self.root = root
        self.root.title("四足机器人数据模拟器")
        self.root.geometry("1000x700")
        self.root.minsize(800, 600)
        
        # 数据生成线程
        self.data_thread = None
        
        # 创建UI
        self.create_ui()
        
        # 加载初始设置
        self.load_settings()
    
    def create_ui(self):
        # 创建主框架
        main_frame = ttk.Frame(self.root, padding="10")
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 创建顶部标题
        title_frame = ttk.Frame(main_frame)
        title_frame.pack(fill=tk.X, pady=(0, 10))
        
        ttk.Label(title_frame, text="四足机器人数据模拟器", font=("Arial", 16, "bold")).pack(side=tk.LEFT)
        
        # 创建左右分栏
        paned = ttk.PanedWindow(main_frame, orient=tk.HORIZONTAL)
        paned.pack(fill=tk.BOTH, expand=True)
        
        # 左侧控制面板
        left_frame = ttk.Frame(paned, padding="5")
        paned.add(left_frame, weight=1)
        
        # 右侧设置面板
        right_frame = ttk.Frame(paned, padding="5")
        paned.add(right_frame, weight=1)
        
        # 创建左侧控制面板内容
        self.create_control_panel(left_frame)
        
        # 创建右侧设置面板内容
        self.create_settings_panel(right_frame)
        
        # 创建底部数据显示区域
        bottom_frame = ttk.LabelFrame(main_frame, text="生成的数据", padding="5")
        bottom_frame.pack(fill=tk.BOTH, expand=True, pady=(10, 0))
        
        self.data_display = scrolledtext.ScrolledText(bottom_frame, height=10, wrap=tk.WORD)
        self.data_display.pack(fill=tk.BOTH, expand=True)
        self.data_display.insert(tk.END, "等待数据生成...\n")
        self.data_display.config(state=tk.DISABLED)
    
    def create_control_panel(self, parent):
        # 自动数据生成控制
        auto_frame = ttk.LabelFrame(parent, text="数据生成控制", padding="10")
        auto_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 10))
        
        # 启用自动数据生成
        self.enable_data_gen = tk.BooleanVar(value=True)
        ttk.Checkbutton(
            auto_frame, 
            text="启用自动数据生成",
            variable=self.enable_data_gen
        ).pack(fill=tk.X, pady=5)
        
        # 生成间隔
        ttk.Label(auto_frame, text="生成间隔（秒）:").pack(anchor=tk.W, pady=(5, 0))
        self.generation_interval = tk.StringVar(value="60")
        interval_spin = ttk.Spinbox(
            auto_frame,
            from_=1,
            to=3600,
            textvariable=self.generation_interval
        )
        interval_spin.pack(fill=tk.X, pady=(0, 5))
        
        # 保存到后端
        self.save_to_backend = tk.BooleanVar(value=True)
        ttk.Checkbutton(
            auto_frame, 
            text="保存到后端数据库",
            variable=self.save_to_backend
        ).pack(fill=tk.X, pady=5)
        
        # 应用设置按钮
        ttk.Button(
            auto_frame,
            text="应用设置",
            command=self.apply_settings
        ).pack(fill=tk.X, pady=(10, 0))
        
        # 手动数据生成
        manual_frame = ttk.LabelFrame(parent, text="手动生成数据", padding="10")
        manual_frame.pack(fill=tk.BOTH, expand=True)
        
        # 保存到数据库选项
        self.manual_save_to_db = tk.BooleanVar(value=True)
        ttk.Checkbutton(
            manual_frame, 
            text="保存到数据库",
            variable=self.manual_save_to_db
        ).pack(fill=tk.X, pady=(0, 10))
        
        # 生成所有类型数据按钮
        ttk.Button(
            manual_frame,
            text="生成所有类型数据",
            style="Accent.TButton",
            command=lambda: self.generate_data("all")
        ).pack(fill=tk.X, pady=(0, 10))
        
        # 创建一个框架来放置按钮
        buttons_frame = ttk.Frame(manual_frame)
        buttons_frame.pack(fill=tk.BOTH)
        
        # 每种数据类型的按钮
        ttk.Button(
            buttons_frame,
            text="生成机器人状态数据",
            command=lambda: self.generate_data("robot_status")
        ).grid(row=0, column=0, padx=(0, 5), pady=5, sticky=tk.EW)
        
        ttk.Button(
            buttons_frame,
            text="生成步态数据",
            command=lambda: self.generate_data("gait_data")
        ).grid(row=0, column=1, padx=(5, 0), pady=5, sticky=tk.EW)
        
        ttk.Button(
            buttons_frame,
            text="生成告警数据",
            command=lambda: self.generate_data("alert")
        ).grid(row=1, column=0, padx=(0, 5), pady=5, sticky=tk.EW)
        
        # 配置网格权重使按钮平均分布
        buttons_frame.columnconfigure(0, weight=1)
        buttons_frame.columnconfigure(1, weight=1)
    
    def create_settings_panel(self, parent):
        notebook = ttk.Notebook(parent)
        notebook.pack(fill=tk.BOTH, expand=True)
        
        # 步态数据设置选项卡
        gait_frame = ttk.Frame(notebook, padding="10")
        notebook.add(gait_frame, text="步态数据设置")
        
        # 步态设置控件
        ttk.Label(gait_frame, text="步幅 (mm):").grid(row=0, column=0, sticky=tk.W, pady=5)
        self.stride_length = tk.StringVar(value="150")
        ttk.Spinbox(
            gait_frame,
            from_=50,
            to=300,
            textvariable=self.stride_length
        ).grid(row=0, column=1, sticky=tk.EW, pady=5)
        
        ttk.Label(gait_frame, text="步高 (mm):").grid(row=1, column=0, sticky=tk.W, pady=5)
        self.step_height = tk.StringVar(value="75")
        ttk.Spinbox(
            gait_frame,
            from_=20,
            to=150,
            textvariable=self.step_height
        ).grid(row=1, column=1, sticky=tk.EW, pady=5)
        
        ttk.Label(gait_frame, text="时间间隔 (s):").grid(row=2, column=0, sticky=tk.W, pady=5)
        self.time_interval = tk.StringVar(value="0.5")
        ttk.Spinbox(
            gait_frame,
            from_=0.1,
            to=1.0,
            increment=0.1,
            textvariable=self.time_interval
        ).grid(row=2, column=1, sticky=tk.EW, pady=5)
        
        ttk.Label(gait_frame, text="点数:").grid(row=3, column=0, sticky=tk.W, pady=5)
        self.point_count = tk.StringVar(value="800")
        ttk.Spinbox(
            gait_frame,
            from_=10,
            to=2000,
            textvariable=self.point_count
        ).grid(row=3, column=1, sticky=tk.EW, pady=5)
        
        ttk.Label(gait_frame, text="结果:").grid(row=4, column=0, sticky=tk.W, pady=5)
        self.gait_result = tk.StringVar(value="正常")
        ttk.Combobox(
            gait_frame,
            values=["正常", "异常"],
            textvariable=self.gait_result,
            state="readonly"
        ).grid(row=4, column=1, sticky=tk.EW, pady=5)
        
        # 列配置
        gait_frame.columnconfigure(1, weight=1)
        
        # 电机数据设置选项卡
        motor_frame = ttk.Frame(notebook, padding="10")
        notebook.add(motor_frame, text="电机数据设置")
        
        # 电机温度
        ttk.Label(motor_frame, text="温度 (°C):").grid(row=0, column=0, sticky=tk.W, pady=5)
        
        self.motor_temps = []
        temp_frame = ttk.Frame(motor_frame)
        temp_frame.grid(row=0, column=1, sticky=tk.EW, pady=5)
        
        for i in range(4):
            var = tk.StringVar(value=str(simulator_settings['motor']['temperature'][i]))
            self.motor_temps.append(var)
            ttk.Spinbox(
                temp_frame,
                from_=20,
                to=70,
                width=5,
                textvariable=var
            ).pack(side=tk.LEFT, padx=2)
        
        # 电机电流
        ttk.Label(motor_frame, text="电流 (A):").grid(row=1, column=0, sticky=tk.W, pady=5)
        
        self.motor_currents = []
        current_frame = ttk.Frame(motor_frame)
        current_frame.grid(row=1, column=1, sticky=tk.EW, pady=5)
        
        for i in range(4):
            var = tk.StringVar(value=str(simulator_settings['motor']['current'][i]))
            self.motor_currents.append(var)
            ttk.Spinbox(
                current_frame,
                from_=-10,
                to=10,
                increment=0.1,
                width=5,
                textvariable=var
            ).pack(side=tk.LEFT, padx=2)
        
        # 列配置
        motor_frame.columnconfigure(1, weight=1)
        
        # 电池和系统设置选项卡
        battery_frame = ttk.Frame(notebook, padding="10")
        notebook.add(battery_frame, text="电池和系统设置")
        
        ttk.Label(battery_frame, text="电池电量 (%):").grid(row=0, column=0, sticky=tk.W, pady=5)
        self.battery_level = tk.StringVar(value="85")
        ttk.Spinbox(
            battery_frame,
            from_=0,
            to=100,
            textvariable=self.battery_level
        ).grid(row=0, column=1, sticky=tk.EW, pady=5)
        
        ttk.Label(battery_frame, text="电池电压 (V):").grid(row=1, column=0, sticky=tk.W, pady=5)
        self.battery_voltage = tk.StringVar(value="25.2")
        ttk.Spinbox(
            battery_frame,
            from_=20,
            to=28,
            increment=0.1,
            textvariable=self.battery_voltage
        ).grid(row=1, column=1, sticky=tk.EW, pady=5)
        
        ttk.Label(battery_frame, text="系统温度 (°C):").grid(row=2, column=0, sticky=tk.W, pady=5)
        self.system_temp = tk.StringVar(value="40")
        ttk.Spinbox(
            battery_frame,
            from_=0,
            to=60,
            textvariable=self.system_temp
        ).grid(row=2, column=1, sticky=tk.EW, pady=5)
        
        # 列配置
        battery_frame.columnconfigure(1, weight=1)
    
    def load_settings(self):
        """加载初始设置"""
        # 步态数据设置
        self.stride_length.set(str(simulator_settings['gait']['stride_length']))
        self.step_height.set(str(simulator_settings['gait']['step_height']))
        self.time_interval.set(str(simulator_settings['gait']['time_interval']))
        self.point_count.set(str(simulator_settings['gait']['point_count']))
        self.gait_result.set(simulator_settings['gait']['result'])
        
        # 电机数据设置
        for i in range(4):
            self.motor_temps[i].set(str(simulator_settings['motor']['temperature'][i]))
            self.motor_currents[i].set(str(simulator_settings['motor']['current'][i]))
        
        # 电池和系统数据设置
        self.battery_level.set(str(simulator_settings['battery']['level']))
        self.battery_voltage.set(str(simulator_settings['battery']['voltage']))
        self.system_temp.set(str(simulator_settings['system']['temperature']))
    
    def save_settings(self):
        """保存设置到全局变量"""
        try:
            # 步态数据设置
            simulator_settings['gait']['stride_length'] = int(self.stride_length.get())
            simulator_settings['gait']['step_height'] = int(self.step_height.get())
            simulator_settings['gait']['time_interval'] = float(self.time_interval.get())
            simulator_settings['gait']['point_count'] = int(self.point_count.get())
            simulator_settings['gait']['result'] = self.gait_result.get()
            
            # 电机数据设置
            for i in range(4):
                simulator_settings['motor']['temperature'][i] = float(self.motor_temps[i].get())
                simulator_settings['motor']['current'][i] = float(self.motor_currents[i].get())
            
            # 电池和系统数据设置
            simulator_settings['battery']['level'] = float(self.battery_level.get())
            simulator_settings['battery']['voltage'] = float(self.battery_voltage.get())
            simulator_settings['system']['temperature'] = float(self.system_temp.get())
            
            return True
        except ValueError as e:
            messagebox.showerror("输入错误", f"设置值格式错误: {str(e)}")
            return False
    
    def apply_settings(self):
        """应用设置"""
        if not self.save_settings():
            return
        
        # 更新自动数据生成设置
        enable_gen = self.enable_data_gen.get()
        interval = int(self.generation_interval.get())
        save_to_db = self.save_to_backend.get()
        
        # 停止当前线程
        if self.data_thread and self.data_thread.is_alive():
            self.data_thread.stop()
            self.data_thread.join(2)  # 等待最多2秒
        
        # 如果启用，创建新线程
        if enable_gen:
            self.data_thread = DataGenerationThread(interval=interval, save_to_db=save_to_db)
            self.data_thread.start()
            messagebox.showinfo("设置已应用", f"自动数据生成已启动，间隔 {interval} 秒")
        else:
            messagebox.showinfo("设置已应用", "自动数据生成已停止")
    
    def generate_data(self, data_type):
        """生成数据"""
        # 保存当前设置
        if not self.save_settings():
            return
        
        save_to_db = self.manual_save_to_db.get()
        
        try:
            if data_type == "all":
                data = generate_and_save_data(save_to_db=save_to_db)
                message = "已生成所有类型数据"
                
            elif data_type == "robot_status":
                data = generate_robot_status()
                message = "已生成机器人状态数据"
                
            elif data_type == "gait_data":
                data = generate_gait_data()
                message = "已生成步态数据"
                
            elif data_type == "alert":
                data = generate_alert_data()
                message = "已生成告警数据"
            
            # 更新数据显示
            self.update_data_display(data, message, save_to_db)
            
        except Exception as e:
            messagebox.showerror("生成数据错误", f"生成数据时出错: {str(e)}")
    
    def update_data_display(self, data, message, save_to_db):
        """更新数据显示区域"""
        save_status = "已保存到数据库" if save_to_db else "未保存到数据库"
        display_text = f"{message} ({save_status})\n\n"
        display_text += json.dumps(data, indent=2, ensure_ascii=False)
        
        self.data_display.config(state=tk.NORMAL)
        self.data_display.delete(1.0, tk.END)
        self.data_display.insert(tk.END, display_text)
        self.data_display.config(state=tk.DISABLED)
        
        # 显示消息框
        messagebox.showinfo("生成成功", f"{message} ({save_status})")

    def on_closing(self):
        """关闭窗口时的处理"""
        if self.data_thread and self.data_thread.is_alive():
            self.data_thread.stop()
            self.data_thread.join(2)  # 等待最多2秒
        self.root.destroy()

if __name__ == "__main__":
    # 设置Tkinter主题
    root = tk.Tk()
    
    # 尝试使用ttk主题
    try:
        from ttkthemes import ThemedStyle
        style = ThemedStyle(root)
        style.set_theme("arc")  # 尝试使用arc主题
    except ImportError:
        style = ttk.Style()
        # 在Windows上使用clam主题
        if root.tk.call('tk', 'windowingsystem') == 'win32':
            style.theme_use('clam')
    
    # 创建一个自定义风格的按钮
    style.configure("Accent.TButton", font=("Arial", 11, "bold"))
    
    app = SimulatorApp(root)
    
    # 设置关闭窗口的处理
    root.protocol("WM_DELETE_WINDOW", app.on_closing)
    
    # 启动主循环
    root.mainloop() 